package bingosoft.metro.datasync.base.service;

import bingosoft.components.base.service.BaseClass;
import bingosoft.components.base.service.Result;
import bingosoft.metro.datasync.base.iservice.ISyncService;
import leap.core.AppContext;
import leap.db.Db;
import leap.lang.Strings;
import leap.orm.dao.Dao;
import leap.orm.model.Model;
import leap.orm.sql.SqlCommand;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Feily
 * @功能描述 全量同步数据服务基础类
 * @创建时间 2017-12-13
 */
public abstract class FullSyncService extends BaseClass implements ISyncService {

	/**
	 * 删除同步数据临时表SQL
	 */
	protected String deleteSyncDataSql;
	/**
	 * 根据同步数据保存目标数据SQL
	 */
	protected String saveTargetDataSql;
	/**
	 * 根据同步数据修改目标数据SQL
	 */
	protected String updateTargetDataSql;
	/**
	 * 根据同步数据删除目标数据SQL
	 */
	protected String deleteTargetDataSql;
	/**
	 * 租户编码
	 */
	protected String tenantCode;

	@Override
	public Result syncData() {
		this.logMethodCalled("syncData");
		
		Result result = new Result();
		String message = "成功同步数据{0}条";
	
		// 获取同步数据信息列表
		List<Model> syncData = this.getSyncDataList();
		if(syncData == null || syncData.size() == 0){
			message = Strings.format(message, 0);
			this.logMessage(message);
			
			result.setMessage(message);
			return result;
		}
		
		try {

			// 删除历史同步数据
			this.deleteSyncData();

			// 保存同步数据
			this.saveSyncData(syncData);

			// 根据同步数据保存或修改目标数据
			if(AppContext.config().getBooleanProperty("sync.syncTargetData", true)){
				this.syncTargetData();
			}

			message = Strings.format(message, syncData.size());
			this.logMessage(message);
			
			result.setMessage(message);
			return result;
			
		} catch (Exception ex) {
			this.logError("同步数据出错", ex);
			
			result.setSuccess(false);
			result.setMessage(ex.getMessage());
			return result;
		}
	}

	public abstract List<Model> getSyncDataList();

	@Override
	public Result deleteSyncData() {
		this.logMethodCalled("deleteSyncData");
	
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("tenantCode", this.tenantCode);
		
		getDao().executeUpdate(this.deleteSyncDataSql, params);
		
		return new Result();
	}

	@Override
	public Result saveSyncData(List<Model> syncData) {
		this.logMethodCalled("saveSyncData");
		
		getDao().batchInsert(syncData);
		
		return new Result();
	}

	@Override
	public Result syncTargetData() {
		this.logMethodCalled("saveOrUpdateTargetData");
	
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("tenantCode", this.tenantCode);

		// 修改目标数据
		getDao().executeUpdate(this.updateTargetDataSql, params);
		
		// 保存目标数据
		getDao().executeUpdate(this.saveTargetDataSql, params);

		if(!Strings.isEmpty(this.deleteTargetDataSql)){
			// 删除目标数据
			getDao().executeUpdate(this.deleteTargetDataSql, params);
		}
		
		return new Result();
	}

	/**
	 * 获取Dao对象
	 * @return
	 */
	protected Dao getDao() {
		return Dao.get();
	}
	
	/**
	 * 获取数据库对象
	 * @return
	 */
	protected Db getDb() {
		return getDao().getOrmContext().getDb();
	}
	
	/**
	 * 获取附加数据库版本的Sql内容
	 * @param sqlKey
	 * @return
	 */
	protected String getSqlContent(String sqlKey) {
		String dbName = "";
		if(getDb().isPostgreSQL()){
			dbName = "postgreSql";
		}else if(getDb().isOracle()){
			dbName = "oracle";
		}else if(getDb().isMySql()){
			dbName = "mySql";
		}else if(getDb().isSqlServer()){
			dbName = "sqlServer";
		}
		
		String newSqlKey = "";
		if(!Strings.isEmpty(dbName)){
			newSqlKey = sqlKey + "$" + dbName;
		}
		
		SqlCommand sqlCommand = Dao.get().getOrmContext().getMetadata().tryGetSqlCommand(newSqlKey);
		if(sqlCommand == null){
			// 如果数据库重载版本不存在，则使用默认SQL
			sqlCommand = Dao.get().getOrmContext().getMetadata().tryGetSqlCommand(sqlKey);
		}
		
		if(sqlCommand == null){
			String message = Strings.format("参数【sqlKey】的值（{0}）不存在", sqlKey);
			throw new RuntimeException(message);
		}
		return sqlCommand.getSql();
	}

	public String getTenantCode() {
		return tenantCode;
	}

	public void setTenantCode(String tenantCode) {
		this.tenantCode = tenantCode;
	}
}